//
//  BleDataTool.swift
//  MMTest
//
//  Created by liujianlong on 2022/9/21.
//

import UIKit
import Foundation
import CoreBluetooth
import TCCKit
///厂商字段
let DeviceName = "DSP8.8BT"
//let DeviceName = "DSP88"

enum BLEData : CCBLEData_protocol{
    ///均衡器<发送通道的频率，Q值，增益>
    case EQ(_ array:[ChannelModel], _ sign_index:Int, _ sign:SignModule)
    ///发送通道正/反相
    case phase(_ channel:ChannelModel)
    ///发送通道延时
    case delay(_ channel:ChannelModel)
    ///发送通道是/否静音, db音量
    case mute(_ channel:ChannelModel)
    ///发送总音量/
    case allMute(_ isMute:Bool, _ vol:Float)
    ///发送分频器
    case crossOver(_ channel:ChannelModel, _ ishigh:Bool)
    ///发送通道直通均衡
    case byPass(_ channel:ChannelModel)
    ///发送通道恢复均衡
    case resetPass(_ channel:ChannelModel)
    ///重置均衡
    case resetEQ(_ channel:ChannelModel?)
    ///获取设备数据<读取设备参数指令>
    case deviceData
    ///发送获取设备数据包后的确认指令
    case deviceDataConfirm(_ seg:Int, _ num:Int)
    ///混音
    case sum(OutputModel)
    /// 上传数据，点击本地设置，同步到设备
    case upload(_ data:[UInt8])
    ///噪声
    case noise(Int)
    
}

extension BLEData{
    var head:[UInt8]{
        switch self{
        case .upload:
            return [UInt8]()
        default :
            return [0xAA,0x55]
        }
    }
    
    var cmd : [UInt8]{
        switch self{
        case .EQ(let array, _, _):
            return array.count == 1 ? [0xAA] : [0xAB]///0xAA~0xAB(单通道、联调)
        case .phase:
            return [0xBB]
        case .delay:
            return [0xCC]
        case  .mute:
            return [0xDB]
        case .allMute:
            return [0xEE]
        case let .crossOver(_, ishigh):
            return ishigh ? [0xDD] : [0xDE]
        case .byPass:
            return [0xFF]
        case .resetPass:
            return [0xFF]
        case .resetEQ:
            return [0xFF]
        case .deviceData,
                .deviceDataConfirm:
            return [0x47, 0x45, 0x54, 0x44, 0x53, 0x50, 0x54, 0x59, 0x55, 0x55]
        case .sum:
            return [0xAA, 0x83, 0xF0]
        case .noise:
            return [0xCC,0xCC]
        default:
            return [UInt8]()
        }
    }
    
    var ack:[UInt8]{
        switch self{
        default:
            return [UInt8]()
        }
        
    }
    
    
    var hex:[UInt8]{
        switch self{
        case .EQ(let array, let sign_index, let sign):
            guard let channel = array.first else{return [UInt8]()}
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            let hex_pd = sign_index.int8.bytesBit///点(0x00~0x0E)
            let hex_frency = sign.frency.int16.bytesBit///频率(0x0014~0x4E20)
            let hex_q = (sign.quality*100).int16.bytesBit ///Q值(0x0005~0x07D0)
            let hex_gain = ((sign.gain+20)*10).int16.bytesBit///增益(0x0000~0x0190)
            let array = hex_pd+hex_frency+hex_q+hex_gain
            return hex_ch+array
        case .phase(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            let hex_phase = channel.phase.int8.bytesBit///正/反相(0x00正，0x01反)
            return hex_ch+hex_phase
        case .delay(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            let hex_time = (channel.delay*100).int16.bytesBit///延时(0x0000~0x03E8))
            return hex_ch+hex_time
        case .mute(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            let hex_mute = channel.mute.int8.bytesBit///是/否静音(0x00否,0x01是)
            let hex_vol = abs(channel.Volume*10).int16.bytesBit///dB音量(0x0000~0x03B6)
            return hex_ch+hex_mute+hex_vol
        case let .allMute(ismute, vol):
            let hex_mute = ismute.int8.bytesBit///是/否静音(0x00否,0x01是)
            let hex_vol = abs(vol*10).int16.bytesBit///dB音量(0x0000~0x03B6)
            return hex_mute+hex_vol
        case let .crossOver(channel, ishigh):
            guard let highPass = channel.highPass else{return [UInt8]()}
            guard let lowPass = channel.lowPass else{return [UInt8]()}
            let filter = ishigh ? highPass : lowPass
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            let hex_type = filterType(filter) ///0x00 bessel,0x01 btr-w,0x02 link-r)
            let hex_slope = filterSlope(filter)///斜率(0x00 6,0x01 12,0x02 24,0x03 48)
            let hex_frency = filter.cutFrency.int16.bytesBit
            return hex_ch+hex_type+hex_slope+hex_frency
        case .byPass(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            return hex_ch+[0x00]
        case .resetPass(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            return hex_ch+[0x01]
        case .resetEQ(let channel):
            let hex_ch = channel == nil ? [0xC0] : hexChannel(channel!)///全部通道EQ重置发通道指令为C0，其他C1-C8为单个通道重置EQ。
            return [0x02]+hex_ch
        case .deviceDataConfirm(let seg, let num):
            let hex_seg = seg.int8.bytesBit /// 0x00~0x01(分段)
            let hex_num = num.int8.bytesBit /// 0x1~0xff(次数)
            return hex_seg+hex_num
        case .sum(let channel):
            let hex_ch = hexChannel(channel)///通道(0xC1~0xC8)
            var hex_array = [UInt8]()
            for input in channel.inputArr{
                hex_array.append(input == "" ? 0x00 : 0x01)
            }
            return hex_ch + hex_array
        case .upload(let data):
            return data
        case .noise(let level):
            return level.int8.bytesBit
        default:
            return [UInt8]()
        }
        
        func hexChannel(_ channel:ChannelModel)->[UInt8]{
            // return "C"+"\(channel.num)"
            let n = 0xC0+UInt8(channel.num)
            return [n]
        }
        
        func filterType(_ filter:FilterModule)->[UInt8]{
            switch filter.type{
            case .bessel:
                return [0x00]
            case .butterW:
                return [0x01]
            case .linkR:
                return [0x02]
            }
        }
        
        func filterSlope(_ filter:FilterModule)->[UInt8]{
            switch filter.slope{
            case 6:
                return [0x00]
            case 12:
                return [0x01]
            case 24:
                return [0x02]
            case 36:
                return[0x03]
            case 48:
                return [0x03]
            default:
                return [UInt8]()
            }
        }
    }
    
    var data:Data{
        var str = self.head + self.cmd + self.hex
        if str.count < 14{
            str+=[UInt8](repeating: 0x00, count: 14-str.count)
        }
        return Data(str)
    }
    
    var service_uuidString:String{
        return "FAA0"
    }
    
    var write_char_uuidString:String{
        return "FAA1"
    }
    var read_char_uuidString:String{
        return "FAA1"
    }
    var errorBlock: (() -> Void)?{
        switch self{
        case .deviceData:
            return {
                CLHUD("No available bluetooth founded!",type:.error, time: 1.5, callBack: nil)
            }
        default:
            return nil
        }
    }
    
}

//MARK: - 蓝牙数据处理
///蓝牙数据处理
class DSBleDataTool : CCBLEData_update_protocol{
    static let share = DSBleDataTool()
    /// 总共收到的数据的条数。< 主板一次性会把总共308条数据发齐，发完要做的一些处理，可以用此参数对比>
    var dataCount = 0
    private init() {}
    ///数据更新
    func handleData(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?){
        let bytes = [UInt8](characteristic.value ?? Data())
        print("数据更新 \(dataCount)= \(bytes.description)")
        if bytes.count < 20 {return}
        
        ///
        dataCount += 1
        
        ///帧头
        let header = [UInt8](bytes[0...1])
        if header == [0xAA,0x00] {
            ///1字节的cmd
            let cmd_1 = [UInt8](bytes[3..<4])
            let num_1 = UInt8(bytes[4])
            let data_1 = [UInt8](bytes[5..<bytes.count])
            
            ///3字节的cmd
            let cmd_3 = [UInt8](bytes[3..<6])
            let num_3 = UInt8(bytes[6])
            
            ///开始筛选
            switch (cmd_1, cmd_3){
                //MARK: - ====>>>>混音
            case (_, BLEData.sum(OutputModel()).cmd):
                let data_3 = [UInt8](bytes[7..<15])
                
                ///遍历output数组
                for output in APP.CHM.out_array{
                    if 0xC0+UInt8(output.num) != num_3 {continue}
                    change(output, data_3)
                }
                
                ///替换output的inputArr，
                func change(_ output:OutputModel, _ data:[UInt8]){
                    for i in 0..<data.count{
                        output.inputArr_custom[i] = Int(data[i]) == 1 ? "\(i+1)" : ""
                    }
                    /// 如果output的inputArr有选中的值，则inputArr大于0，则output肯定是选中
                    let sum = output.inputArr_custom.map{Int($0) ?? 0}.reduce(0, +)
                    output.select = sum > 0
                }
                //MARK: - ====>>>>均衡器
            case ([0xAA], _),
                ([0xAB], _):
                ///遍历channel数组
                for ch in APP.CHM.array{
                    if 0xC0+UInt8(ch.num) != num_1 {continue}
                    ///遍历channel的信号数组signArray
                    let sign_index = Int(data_1[0])
                    for i in 0..<ch.signArray.count{
                        if i + 1 != sign_index {continue}
                        let sign = ch.signArray[i]
                        change(sign, data_1)
                    }
                }
                
                ///替换信号模块的值
                func change(_ sign:SignModule, _ data:[UInt8]){
                    sign.frency = [UInt8](data[1..<3]).int
                    sign.quality = Float([UInt8](data[3..<5]).int) / 100.0
                    sign.gain = Float([UInt8](data[5..<7]).int) / 10.0 - 20.0
                }
                //MARK: - ====>>>>通道正/反相
            case (BLEData.phase(ChannelModel()).cmd, _):
                ///遍历channel数组
                for ch in APP.CHM.array{
                    if 0xC0+UInt8(ch.num) != num_1 {continue}
                    changePhase(ch, data_1)
                }
                
                ///替换channel的正反相
                func changePhase(_ ch:ChannelModel, _ data:[UInt8]){
                    ch.phase = UInt8(data[0]) == 0
                }
                //MARK: - ====>>>>通道延迟
            case (BLEData.delay(ChannelModel()).cmd, _):
                ///遍历channel数组
                for ch in APP.CHM.array{
                    if 0xC0+UInt8(ch.num) != num_1 {continue}
                    changeDelay(ch, data_1)
                }
                
                ///替换channel的通道延迟
                func changeDelay(_ ch:ChannelModel, _ data:[UInt8]){
                    ch.delay = Float([UInt8](data[0..<2]).int) / 100.0
                }
                //MARK: - ====>>>>通道静音，音量
            case (BLEData.mute(ChannelModel()).cmd, _):
                ///遍历channel数组
                for ch in APP.CHM.array{
                    if 0xC0+UInt8(ch.num) != num_1 {continue}
                    changeMute(ch, data_1)
                }
                
                ///替换channel的通道静音，音量
                func changeMute(_ ch:ChannelModel, _ data:[UInt8]){
                    ch.mute = Int(data[0]) == 1
                    ch.Volume = Int16([UInt8](data[1..<3]).int == 0 ? 0 : [UInt8](data[1..<3]).int / 10 - 50)
                }
                //MARK: - ====>>>>总通道音量
            case (BLEData.allMute(true, 0).cmd, _):
                APP.CHM.mute = Int(data_1[0]) == 1
                APP.CHM.volume = [UInt8](data_1[1..<3]).int == 0 ? 0 : [UInt8](data_1[1..<3]).int / 10 - 50
                //MARK: - ====>>>>分频器
            case ([0xDD], _),///highPass
                ([0xDE], _):///lowPass
                ///遍历channel数组
                for ch in APP.CHM.array{
                    if 0xC0+UInt8(ch.num) != num_1 {continue}
                    changeCrossOver(ch, data_1, cmd_1)
                }
                ///替换channel的分频器
                func changeCrossOver(_ channel:ChannelModel, _ data:[UInt8], _ cmd:[UInt8]){
                    guard let filter = cmd == [0xDD] ? channel.highPass : channel.lowPass else{return}
                    let type = UInt8(data[0])
                    let slope = UInt8(data[1])
                    switch type{
                    case 0x00:
                        filter.type = .bessel
                    case 0x01:
                        filter.type = .butterW
                    case 0x02 :
                        filter.type = .linkR
                    default:
                        break
                    }
                    switch slope{
                    case 0x00:
                        filter.slope = 6
                    case 0x01:
                        filter.slope = 12
                    case 0x02:
                        filter.slope = 24
                    case 0x03:
                        filter.slope = 48
                    default:
                        break
                    }
                    filter.cutFrency = [UInt8](data[2..<4]).int
                }
            default:
                break
            }
        }
        ///数据传输完成
        if dataCount >= 308 {
            
            ///重置全局通道的inputSelectType的模式
            APP.CHM.inputSelectType = 0
            
            for output in APP.CHM.out_array{
                let sum = output.inputArr_custom.map{Int($0) ?? 0}.reduce(0, +)
                
                ///1，如果全局管理的inputSelectType模式是0，
                ///并且每个output的inputArr，没有选中任何input
                ///那么inputSelectType模式 = 0
                if APP.CHM.inputSelectType == 0 && sum == 0{
                    APP.CHM.inputSelectType = 0
                }
                ///2，如果全局管理的inputSelectType模式是Custom，
                ///并且每个output的inputArr，又只有选中output本身对应的input
                ///那么inputSelectType模式 = Assign
                else if APP.CHM.inputSelectType == 1 && output.num == sum{
                    APP.CHM.inputSelectType = 1
                }
                ///3，不管全局管理的inputSelectType模式是任何模式，
                ///只要有一个output的inputArr，没有选中output本身对应的input
                ///那么inputSelectType模式 = Custom
                else if output.num != sum && sum > 0{
                    APP.CHM.inputSelectType = 2
                }
            }
            
            CLHUD("Upload successfully",type: .success,time: 1.5, callBack: nil)
            NotifyTool.post(updateChannelManager)
            //let copy_chm = APP.CHM.copy()
            //RealmHelper.updateObject(object: copy_chm)
        }
    }
}


